<?
require_once dirname(__FILE__) . '/../../system/core/Model.php';

class Base extends CI_Model {
	
	public $__dm;
	
	public function __construct($tabela = null) {
		parent::__construct();

		$this->__dm['tabela'] = $tabela ? $tabela : strtolower(get_class($this));
		
		$this->getAtributos();
	}
	
	
	private function getAtributos(){
		$CI = &get_instance();

		$campos = $CI->db->field_data($this->__dm['tabela']);
		foreach ($campos as $campo => $atributo) {
			if ($atributo->primary_key)
				$this->__dm['primaria'] = $atributo->name;
			$this->{$atributo->name} = NULL;
		}
	}
	
	
	public function validate() {
		$this->load->library('validate');

		$vars = get_object_vars($this);
		$nome_classe = get_class($this);

		foreach ($vars as $atributo => $valor) {
			if (method_exists($this, "validate_$atributo")) {
				$retorno["{$nome_classe}_{$atributo}"] = $this->{"validate_$atributo"}();
			}
		}
		return (in_array(false, $retorno) ? $retorno : true);
	}


	/**
	 * inserir: Insere o objeto
	 * 
	 * @return int: Numero do ID criado
	 */
	public function inserir() {
		$obj = clone($this);
		unset($obj->__dm);
		$this->db->insert($this->__dm['tabela'], $obj);
    	return $this->db->insert_id();
	}
	
	
	/**
	 * alterar: Altera conforme todos os atributos do objeto (deve existir chave primaria) 
	 */
	public function alterar() {

		$obj = clone($this);
		unset($obj->__dm);
		
		$this->db->where($this->__dm['primaria'], $obj->{$this->__dm['primaria']});
		
		$vars = get_object_vars($obj);

		if (count(get_object_vars($obj)) > 0)
			$this->db->update($this->__dm['tabela'], $obj);
	}
	
	
	/**
	 * alterarEspecifico: altera somente os atributos que foram especificado utilizando a chave
	 * 					  primaria definida
	 */
	public function alterarEspecificado() {
		$obj = clone($this);
		unset($obj->__dm);
		
		$this->db->where($this->__dm['primaria'], $obj->{$this->__dm['primaria']});
		
		$vars = get_object_vars($obj);
		foreach ($vars as $posicao => $valor) {
			if (!isset($valor))
				unset($obj->$posicao);
		}

		if (count(get_object_vars($obj)) > 0)
			$this->db->update($this->__dm['tabela'], $obj);
	}
	
	
	/**
	 * excluir: Exclui conforme definido no objeto
	 */
	public function excluir() {
		$obj = clone($this);
		unset($obj->__dm);
		
		$pode_excluir = false;
		
		$vars = get_object_vars($obj);
		foreach ($vars as $campo => $valor) {
			if ($valor) {
				$this->db->where($campo, $valor);
				$pode_excluir = true;
			}
		}
		
		if ($pode_excluir) $this->db->delete($this->__dm['tabela']);
	}
	
	public function condicao($where, $operador = 'and') {
		$operador = strtolower($operador);
		
		if ($operador == 'or') {
			$this->db->or_where($where);
		}
		else {
			$this->db->where($where);
		}
	}
	
	
	public function ordenarPor($ordenacao) {
		$this->db->order_by($ordenacao);
	}
	
	
	public function limite($limite, $inicio = 0) {
		$this->db->limit($limite, $inicio);
	}
	
	
	private function _query() {
		$obj = clone($this);
		unset($obj->__dm);
		
		$vars = get_object_vars($obj);
		foreach ($vars as $campo => $valor) {
			if (isset($valor) && $valor != '%') {
				if (preg_match('/%/', $valor)) {
					$valor = str_replace('%', '', $valor);
					$this->db->like($this->__dm['tabela'].'.'.$campo, $valor);
				}
				else
					$this->db->where($this->__dm['tabela'].'.'.$campo, $valor);
			}
		}
	}
	
	public function join($tabela, $campo) {
		$this->db->join($tabela, "$tabela.$campo = {$this->__dm['tabela']}.$campo", 'left');
	}
	
	
	/**
	 * @return ArrayOfObject
	 */
	public function recuperar() {
		$this->_query();
		
		$this->db->from($this->__dm['tabela']);
		return $this->db->get()->result();
	}
	
	public function total() {
		$this->_query();
		
		$this->db->from($this->__dm['tabela']);
		return $this->db->count_all_results();
	}


	public function setFrom($de) {
		
		$tipo = gettype($de);

		switch ($tipo) {

			case 'array':
				foreach ($this as $campo => $valor)
					if (isset($de[$campo]) && $de[$campo])
						$this->$campo = $de[$campo];
				break;

			case 'object':
				foreach ($this as $campo => $valor)
					if (isset($de->$campo) && $de->$campo)
						$this->$campo = $de->$campo;
				break;

		}
	}
	
		
	public function iniciaTransacao(){
		$this->db->trans_start();
	}

	public function finalizaTransacao(){
		$this->db->trans_complete();
	}
	
}